/**
 * 
 */
package com.cqan.session;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeoutException;

import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.exception.MemcachedException;

import org.apache.catalina.Manager;
import org.apache.catalina.SessionListener;
import org.apache.catalina.session.StandardSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.cqan.manager.MemcachedManager;

/**
 * @Description 重写 Session 中部分方法，把session中内容同步到memcached中
 * @author wuhui
 * @date 2012-5-25下午3:18:06
 * 
 */
public class MemcachedSession extends StandardSession {

	protected transient MemcachedClient client = null;

	private static Logger logger = LoggerFactory.getLogger(MemcachedSession.class);

	/**
	 * 设置memcachedSession session数据有效期
	 */
	private transient  int exp = 30 * 60;
	
	private transient int timeout = 10;

	/**
	 * @param manager
	 */
	public MemcachedSession(Manager manager) {
		super(manager);

	}
	

	public MemcachedSession(Manager manager, MemcachedClient client) {
		super(manager);
		this.client = client;
	}

	public MemcachedSession(Manager manager, MemcachedClient client, int exp) {
		super(manager);
		this.client = client;
		this.exp = exp;
	}

	public Object getAttribute(String name) {
		Object obj = super.getAttribute(name);
		if (obj != null && !(obj instanceof Serializable)) {
			return obj;
		}
		String key = getKey(name, this.getId());
		try {
			obj = client.get(key,timeout);
			logger.debug("getAttribute key={} value={}",new Object[] { key, obj});
		} catch (TimeoutException e) {
			logger.error("getAttribute error " + e.getMessage());
		} catch (InterruptedException e) {
			logger.error("get memcached error " + e.getMessage());
		} catch (MemcachedException e) {
			logger.error("getAttribute error " + e.getMessage());
		}
		return obj;
	}

	@Override
	public void setAttribute(String name, Object value) {
		removeAttribute(name);
		super.setAttribute(name, value);
		if (value != null && value instanceof java.io.Serializable) {
			String key = getKey(name, this.getId());
			try {
				client.set(key, exp, value);
				logger.debug("setAttribute key={} value={}", new Object[] { key, value});
			} catch (TimeoutException e) {
				logger.error("setAttribute error " + e.getMessage());
			} catch (InterruptedException e) {
				logger.error("setAttribute error " + e.getMessage());
			} catch (MemcachedException e) {
				logger.error("setAttribute error " + e.getMessage());
			}
		}
	}
	
	protected void removeAttributeInternal(String name, boolean notify) {
        super.removeAttributeInternal(name, notify);
        String key = getKey(name, this.getId());
        try {
			client.delete(key);
		} catch (TimeoutException e) {
			logger.error("removeAttributeInternal error " + e.getMessage());
		} catch (InterruptedException e) {
			logger.error("removeAttributeInternal error " + e.getMessage());
		} catch (MemcachedException e) {
			logger.error("removeAttributeInternal error " + e.getMessage());
		}
    }

    public void expire(boolean notify) {
    	try {
			client.delete(((MemcachedManager) manager).getPerfix() + this.getId());
		} catch (TimeoutException e) {
			logger.error("expire error " + e.getMessage());
		} catch (InterruptedException e) {
			logger.error("expire error " + e.getMessage());
		} catch (MemcachedException e) {
			logger.error("expire error " + e.getMessage());
		}
        super.expire(notify);
    }
    
    public void doAfterDeserialization() {
        if ( listeners == null ) {
            listeners = new ArrayList<SessionListener>();
        }
        if ( notes == null ) {
            notes = new ConcurrentHashMap<String, Object>();
        }
    }
    
    private String getKey(String name,String id){
		return new StringBuffer(name).append("_").append(id).toString();
    	
    }
}
